package com.xuecheng.media.infrastructure.util;

import com.xuecheng.base.exception.XueChengPlusException;
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Component
public class MinioUtil {

    @Autowired
    private MinioClient minioClient;

    /**
     * 获取某个文件流
     * @param bucket
     * @param filePath
     * @return
     */
    public InputStream getObjStream(String bucket, String filePath){
        InputStream inputStream = null;
        try {
            inputStream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucket)
                            .object(filePath)
                            .build());
        } catch (Exception e) {
        }
        return inputStream;
    }

    /**
     * 获取某个分片文件
     * @param bucket
     * @param filePath
     * @return
     */
    public ComposeSource getComposeSource(String bucket, String filePath){
        try {
            return ComposeSource.builder()
                    .bucket(bucket)
                    .object(filePath)
                    .build();
        } catch (Exception e) {
            throw new XueChengPlusException("获取分片文件出错");
        }
    }

    /**
     * 合并分片
     * @param bucket
     * @param filePath
     * @param composeSources
     * @return
     */
    public void mergeComposeSource(String bucket, String filePath,
                                                List<ComposeSource> composeSources){
        try {
            minioClient.composeObject(
                    ComposeObjectArgs.builder()
                        .bucket(bucket)
                        .object(filePath)
                        .sources(composeSources)
                        .build()
            );
        } catch (Exception e) {
            log.error("合并分片出错，原因：{}", e.getMessage());
            throw new XueChengPlusException("合并分片出错");
        }
    }

    /**
     * 获取文件对象
     * @param bucket
     * @param filePath
     * @return
     */
    public File getObj(String bucket, String filePath){
        File resFile = null;
        FileOutputStream outputStream;
        try {
            InputStream objStream = getObjStream(bucket, filePath);
            if (Objects.isNull(objStream)){
                return null;
            }
            resFile = File.createTempFile("minio", "tmp");
            outputStream = new FileOutputStream(resFile);
            IOUtils.copy(objStream, outputStream);
            outputStream.close();
        } catch (Exception e){
           log.debug("获取对象不存在");
        }
        return resFile;
    }

    /**
     * 清理分片文件
     * @param chunkPath
     * @param chunkTotal
     */
    public void clearChunkPath(String chunkPath, Integer chunkTotal, String bucket) {
        List<DeleteObject> deleteObjects = new ArrayList<>();
        try {
            for (int i = 0; i < chunkTotal; i++){
                deleteObjects.add(new DeleteObject(chunkPath + i));
            }
            RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder()
                    .bucket(bucket)
                    .objects(deleteObjects)
                    .build();
            // 删除
            Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs);
            // 检验是否已经删除
            for (Result<DeleteError> result : results) {
                DeleteError deleteObject = null;
                try {
                    deleteObject = result.get();
                } catch (Exception e) {
                    throw new XueChengPlusException("清楚分片失败");
                }
            }
        } catch (Exception e){
            throw new XueChengPlusException("获取对象出错");
        }
    }


    /**
     * 删除文件夹
     * @param bucket
     * @param file
     * @return
     */
    public Boolean removeFile(String bucket, String file){
        try {
            ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder()
                    .bucket(bucket)
                    .prefix(file)
                    .recursive(true)
                    .build();
            Iterable<Result<Item>> resultIterable = minioClient.listObjects(listObjectsArgs);
            Integer count = 0;
            for (Result<Item> result : resultIterable) {
                count ++;
            }
            this.clearChunkPath(file, count, bucket);
            return false;
        } catch (Exception e){
            log.error("删除文件出错，错误原因：{}", e.getMessage());
        }
        return true;
    }
}
